package com.sds.service.impl;

import com.sds.service.VisibilityService;
import org.springframework.stereotype.Service;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

@Service
public class VisibilityServiceImpl implements VisibilityService {

    private volatile boolean volatileFlag = true;
    private static boolean synchronizedFlag = true;
    private boolean lockFlag = true;
    private final boolean finalFlag = true;

    private final Object syncLock = new Object();
    private final Lock lock = new ReentrantLock();

    /**
     * volatile关键字
     */
    @Override
    public void volatileMethod() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (volatileFlag) {
                // ....
            }
            System.out.println("t1线程结束");
        });
        t1.start();
        Thread.sleep(10);
        volatileFlag = false;
        System.out.println("主线程将volatileFlag修改为false");
    }

    /**
     * synchronized关键字
     */
    @Override
    public void synchronizedMethod() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            while (synchronizedFlag) {
                synchronized (syncLock) {
                    // ....
                }
            }
            System.out.println("t1线程结束");
        });
        t1.start();
        Thread.sleep(10);
        synchronizedFlag = false;
        System.out.println("主线程将synchronizedFlag修改为false");
    }

    /**
     * lock锁
     */
    @Override
    public void lockMethod() {
        Thread t1 = new Thread(() -> {
            while (true) {
                lock.lock();
                try {
                    if (!lockFlag) break;
                } finally {
                    lock.unlock();
                }
            }
            System.out.println("t1线程结束");
        });
        t1.start();
        lock.lock();
        try {
            lockFlag = false;
        } finally {
            lock.unlock();
        }
    }

    /**
     * final关键字
     * final修饰的属性，在运行期间是不允许修改的，这样一来，就间接的保证了可见性
     */
    @Override
    public void finalMethod() {
        Thread t1 = new Thread(() -> {
            while (finalFlag) {
                // ....
            }
            //System.out.println("t1 thread ends");
        });
        t1.start();
    }
}